﻿using InTheHand.Bluetooth;
using InTheHand.Net;
using InTheHand.Net.Bluetooth;
using InTheHand.Net.Sockets;

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Management;
using System.Net.Sockets;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;

namespace UCTT.NetFx.BTComm
{
    /// <summary>
    /// 用于控制蓝牙获取、扫描、配对、连接等功能的工具类
    /// </summary>
    public class BluetoothService
    {
        #region    字段 start
        private readonly TimeSpan InquiryLength = TimeSpan.FromSeconds(1.5);
        private readonly Guid Guid = InTheHand.Net.Bluetooth.BluetoothService.SerialPort;
        private readonly List<BluetoothDevice> BTDeviceList;// 经典蓝牙设备列表
        private readonly List<BluetoothDevice> BLEDeviceList;// 低功耗蓝牙设备列表
        private readonly List<BluetoothDeviceInfo> DeviceInfoList;// 蓝牙设备信息列表
        private readonly List<string> CommonPins = new List<string> { "0000", "1111", "1234" };// 连接经典蓝牙设备的通用pin码

        private readonly ConcurrentQueue<byte[]> rqRawData;// 存储经典蓝牙接收数据的队列

        private bool isStopScanBTDevice;// 是否停止搜索经典蓝牙设备
        private BluetoothLEScan bleScan;// ble扫描器
        private BluetoothDeviceInfo btDeviceInfo;// 已连接的BT设备
        private RemoteGattServer remoteGattServer;// 已连接的BLE设备
        private IReadOnlyList<GattCharacteristic> bcafChttLst;// 特定通信特性的集合
        private Socket client;
        private NetworkStream stream;
        #endregion 字段 end

        #region    属性 start
        /// <summary>
        /// 主蓝牙适配器
        /// </summary>
        public BluetoothRadio PrimaryRadio { get; private set; }
        /// <summary>
        /// 蓝牙适配器是否可用
        /// </summary>
        public bool IsRadioReady { get; private set; }
        /// <summary>
        /// 经典蓝牙设备信息列表
        /// </summary>
        public List<BluetoothDeviceInfo> BTDeviceInfoList { get; set; } = new List<BluetoothDeviceInfo>();
        /// <summary>
        /// BT客户端信息列表
        /// </summary>
        public List<(string, int, bool)> BTClientInfoList { get; set; } = new List<(string, int, bool)>();
        /// <summary>
        /// BLE客户端信息列表
        /// </summary>
        public List<(string, short, bool)> BLEClientInfoList { get; set; } = new List<(string, short, bool)>();
        /// <summary>
        /// 本地终结点
        /// </summary>
        public BluetoothEndPoint LocalEndpoint { get; private set; }
        /// <summary>
        /// 本地客户端
        /// </summary>
        public BluetoothClient LocalClient { get; private set; }
        /// <summary>
        /// 特征服务列表(仅Ble设备)
        /// </summary>
        public List<GattService> GattServiceList { get; private set; } = new List<GattService>();
        /// <summary>
        /// 特征列表(仅Ble设备)
        /// </summary>
        public List<GattCharacteristic> GattCharacteristicList { get; private set; } = new List<GattCharacteristic>();
        #endregion 属性 end

        #region    结构体 start
        public struct SerialPort
        {
            public string Port;
            public string DeviceId;
        }
        #endregion 结构体 end

        #region    委托与事件 start
        public delegate void RadioStateChangedEvent(bool isReady);
        /// <summary>
        /// 反馈蓝牙适配器状态的事件
        /// </summary>
        public event RadioStateChangedEvent RadioStateChanged;
        public delegate void eventRun(int type, string str, byte[] data = null);
        public event eventRun ValueChanged;
        public delegate void UpdateBTDevciceEvent(List<(string, int, bool)> infoList, List<BluetoothDeviceInfo> deviceInfoLst);
        /// <summary>
        /// 更新搜索到的经典蓝牙设备的事件
        /// </summary>
        public event UpdateBTDevciceEvent UpdateBTDevcice;
        public delegate void UpdateBLEDevciceEvent(BluetoothAdvertisingEvent e, (string, short, bool) newItem);
        /// <summary>
        /// 更新搜索到的低功耗蓝牙设备的事件
        /// </summary>
        public event UpdateBLEDevciceEvent UpdateBLEDevcice;

        /// <summary>
        /// 反馈经典蓝牙设备连接状态的事件
        /// </summary>
        public event AsyncCallback BTConnected;

        public delegate void ReceivedEvent(BluetoothDeviceInfo e, Socket client, NetworkStream stream);
        public event ReceivedEvent Received;
        public Action SearchStoped;
        #endregion 委托与事件 start

        #region    构造与析构 start
        public BluetoothService()
        {
            rqRawData = new ConcurrentQueue<byte[]>();

            PrimaryRadio = BluetoothRadio.Default;
            IsRadioReady = PrimaryRadio != null;
            LocalClient = new BluetoothClient { InquiryLength = this.InquiryLength };
            client = LocalClient.Client;

            BLEDeviceList = new List<BluetoothDevice>();
            DeviceInfoList = new List<BluetoothDeviceInfo>();
            Bluetooth.AvailabilityChanged += Bluetooth_AvailabilityChanged;
            Bluetooth.AdvertisementReceived += Bluetooth_AdvertisementReceived;

            //if (IsRadioReady)
            //{
            //    var btAddr = PrimaryRadio.LocalAddress;
            //    LocalEndpoint = new BluetoothEndPoint(btAddr, Guid);
            //}
        }
        #endregion 构造与析构 end

        #region    事件处理 start
        // 蓝牙适配器打开/关闭事件
        private async void Bluetooth_AvailabilityChanged(object sender, EventArgs e)
        {
            PrimaryRadio = BluetoothRadio.Default;
            IsRadioReady = await Bluetooth.GetAvailabilityAsync();
            //Trace.WriteLine(IsRadioReady ? "蓝牙已打开" : "蓝牙已关闭");
            RadioStateChanged.Invoke(IsRadioReady);
        }

        // 接收BLE广播事件 => 获取BLE设备列表
        private void Bluetooth_AdvertisementReceived(object sender, BluetoothAdvertisingEvent e)
        {
            if (e.Device != null)
            {
                var dev = e.Device;
                dev.GattServerDisconnected += Dev_GattServerDisconnected;
                if (!BLEDeviceList.Exists(device => device.Id == e.Device.Id))
                {
                    BLEDeviceList.Add(dev);
                }
                var devName = string.IsNullOrWhiteSpace(dev.Name) ? "Unknown" : dev.Name;
                var devStr = $"{dev.Id}({devName})";
                if (!BLEClientInfoList.Exists(info => info.Item1 == devStr))
                {
                    var newItem = (devStr, e.Rssi, dev.IsPaired);
                    BLEClientInfoList.Add(newItem);
                    UpdateBLEDevcice?.Invoke(e, newItem);
                }
            }
        }

        // BLE设备断开连接事件
        private void Dev_GattServerDisconnected(object sender, EventArgs e)
        {
        }

        // BLE特性值变更通知 => 获取BLE设备的特性值
        private void Chtt_CharacteristicValueChanged(object sender, GattCharacteristicValueChangedEventArgs e)
        {
            var data = e.Value;
            var str = BitConverter.ToString(data);
            Trace.WriteLine($"长度：{data.Length}\r\n值：{str}");
        }
        #endregion 事件处理 end

        #region    公开方法 start
        /// <summary>
        /// 开始搜索经典蓝牙设备
        /// </summary>
        public void StartScan()
        {
            Task.Factory.StartNew(() =>
            {
                isStopScanBTDevice = false;
                while (!isStopScanBTDevice)
                {
                    var deviceInfos = LocalClient.DiscoverDevices();
                    BTDeviceInfoList = deviceInfos.ToList();
                    BTDeviceInfoList.ForEach(info =>
                    {
                        var name = info.DeviceName;
                    });
                    Trace.WriteLine($"StartScan.BTClientInfoList.Count={BTDeviceInfoList.Count}");
                    UpdateBTDevcice?.Invoke(BTClientInfoList, BTDeviceInfoList);
                }
            });
        }

        /// <summary>
        /// 开始搜索低功耗蓝牙设备
        /// </summary>
        /// <returns></returns>
        public async Task StartScanLEAsync()
        {
            BLEClientInfoList.Clear();
            bleScan = await Bluetooth.RequestLEScanAsync(new BluetoothLEScanOptions { AcceptAllAdvertisements = true });
            //var device = await Bluetooth.RequestDeviceAsync(new RequestDeviceOptions { AcceptAllDevices = true });
            //Trace.WriteLine(device);
        }

        /// <summary>
        /// 停止搜索经典蓝牙设备
        /// </summary>
        public void StopScan()
        {
            isStopScanBTDevice = true;
            UpdateClient();
        }

        /// <summary>
        /// 停止搜索低功耗蓝牙设备
        /// </summary>
        public void StopScanLE()
        {
            bleScan?.Stop();
        }

        /// <summary>
        /// 连接指定地址的BT设备
        /// </summary>
        /// <param name="macAddr">指定地址</param>
        public bool Connect(BluetoothDeviceInfo bdi)
        {
            return Connect(bdi, Guid);
        }

        public bool Connect(BluetoothDeviceInfo bdi, Guid guid)
        {
            if (bdi.DeviceAddress == BluetoothAddress.None)
            {
                throw new ArgumentNullException(nameof(bdi.DeviceAddress));
            }
            var success = false;
            try
            {
                if (BluetoothSecurity.PairRequest(bdi.DeviceAddress, CommonPins[0]))
                {
                    LocalClient.Connect(bdi.DeviceAddress, guid);
                    success = LocalClient.Connected;
                    if (success)
                    {
                        if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
                        {
                            bdi.SetServiceState(guid, true);
                        }
                        //var serviceGuids = bdi.InstalledServices;
                        //foreach (var item in serviceGuids)
                        //{
                        //    var srb = new ServiceRecordBuilder();
                        //    srb.AddServiceClass(item);
                        //    var sr = srb.ServiceRecord;
                        //    foreach (var id in sr.AttributeIds)
                        //    {
                        //        var sa = sr.GetAttributeById(id);
                        //    }
                        //}
                        btDeviceInfo = bdi;

                        DataReceived();
                    }
                }
                else
                {
                    Trace.WriteLine($"认证失败！");
                }
            }
            catch
            {
                throw;
            }
            return success;
        }

        public bool Disconnect()
        {
            var success = false;
            if (LocalClient.Connected)
            {
                success = BluetoothSecurity.RemoveDevice(btDeviceInfo.DeviceAddress);
            }
            return success;
        }

        /// <summary>
        /// 异步连接指定地址的BT设备
        /// </summary>
        /// <param name="macAddr">指定地址</param>
        /// <returns></returns>
        public async Task ConnectAsync(BluetoothDeviceInfo bdi)
        {
            await ConnectAsync(bdi, Guid);
        }

        /// <summary>
        /// 异步连接指定地址和服务的BT设备
        /// </summary>
        /// <param name="macAddr">指定地址</param>
        /// <param name="guid">指定服务的标识符</param>
        /// <returns></returns>
        /// <exception cref="ArgumentNullException"></exception>
        public async Task ConnectAsync(BluetoothDeviceInfo bdi, Guid guid)
        {
            if (bdi.DeviceAddress == BluetoothAddress.None)
            {
                throw new ArgumentNullException(nameof(bdi.DeviceAddress));
            }

            (bool success, IAsyncResult asyncResult) = (false, null);
            if (BluetoothSecurity.PairRequest(bdi.DeviceAddress, CommonPins[0]))
            {
                await LocalClient.ConnectAsync(bdi.DeviceAddress, guid);
                success = LocalClient.Connected;
            }
            else
            {
                Trace.WriteLine($"认证失败！");
            }
        }

        public async Task<bool> ConnectLEAsync(BluetoothDevice device)
        {
            return await ConnectLEAsync(device, BluetoothUuid.Empty);
        }

        /// <summary>
        /// 连接指定的BLE设备
        /// </summary>
        /// <param name="device">指定的BLE设备</param>
        /// <returns></returns>
        public async Task<bool> ConnectLEAsync(BluetoothDevice device, BluetoothUuid uuid)
        {
            remoteGattServer = device.Gatt;
            await remoteGattServer.ConnectAsync();
            var isConnected = remoteGattServer.IsConnected;
            if (isConnected)
            {
                GattServiceList = await remoteGattServer.GetPrimaryServicesAsync();
                GattServiceList.ForEach(async x =>
                {
                    var chttLst = await x.GetCharacteristicsAsync();
                    GattCharacteristicList.AddRange(chttLst.AsEnumerable());
                });
                //var gattServiceLst = await remoteGattServer.GetPrimaryServicesAsync();
                //if (uuid == BluetoothUuid.Empty)
                //{
                //    foreach (var gattService in gattServiceLst)
                //    {
                //        var bcafChttLst = await gattService.GetCharacteristicsAsync();
                //        foreach (var chtt in bcafChttLst)
                //        {
                //            chtt.CharacteristicValueChanged += Chtt_CharacteristicValueChanged;
                //            try
                //            {
                //                await chtt.StartNotificationsAsync();
                //            }
                //            catch (Exception ex)
                //            {
                //                Trace.WriteLine(ex.Message);
                //            }
                //        }
                //    }
                //}
                //else
                //{
                //    var bcafService = gattServiceLst.FirstOrDefault(gattService => gattService.Uuid == BluetoothUuid.Empty);
                //    var bcafChttLst = await bcafService?.GetCharacteristicsAsync();
                //    foreach (var chtt in bcafChttLst)
                //    {
                //        chtt.CharacteristicValueChanged += Chtt_CharacteristicValueChanged;
                //        try
                //        {
                //            await chtt.StartNotificationsAsync();
                //        }
                //        catch (Exception ex)
                //        {
                //            Trace.WriteLine(ex.Message);
                //        }
                //    }
                //}
            }
            return isConnected;
        }

        /// <summary>
        /// 断开当前连接的BLE设备
        /// </summary>
        public async Task DisconnectLE()
        {
            if (bcafChttLst != null)
            {
                foreach (var chtt in bcafChttLst)
                {
                    await chtt.StopNotificationsAsync();
                }
            }
            remoteGattServer.Disconnect();
        }

        /// <summary>
        /// 返回指定Uuid的特征(仅限Ble设备)
        /// </summary>
        /// <param name="uuid">指定Uuid</param>
        /// <returns>Gatt特征</returns>
        public GattCharacteristic GetGattCharacteristic(BluetoothUuid uuid)
        {
            var chtt = GattCharacteristicList.FirstOrDefault(x => x.Uuid == uuid);
            return chtt;
        }

        /// <summary>
        /// 返回指定Uuid服务的所有特征(仅限Ble设备)
        /// </summary>
        /// <param name="uuid">指定服务的Uuid</param>
        /// <returns>所有Gatt特征</returns>
        public async Task<List<GattCharacteristic>> GetGattCharacteristicList(BluetoothUuid uuid)
        {
            var gattService = GattServiceList.FirstOrDefault(x => x.Uuid == uuid);
            var chttLst = await gattService?.GetCharacteristicsAsync();
            return chttLst.ToList();
        }

        /// <summary>
        /// 获取指定mac地址的蓝牙设备
        /// </summary>
        /// <param name="address">mac地址</param>
        /// <returns>蓝牙设备信息</returns>
        public BluetoothDeviceInfo DeviceByAdress(string address)
        {
            try
            {
                return new BluetoothDeviceInfo(BluetoothAddress.Parse(address));
            }
            catch
            {
                return null;
            }
        }

        /// <summary>
        /// 打印所有已配对的蓝牙设备
        /// </summary>
        public void PrintPairedDevices()
        {
            DeviceInfoList.AddRange(LocalClient.DiscoverDevices());
            PrintDevices();
        }

        /// <summary>
        /// 打印所有蓝牙设备
        /// </summary>
        public void PrintAllDevices()
        {
            DeviceInfoList.AddRange(LocalClient.DiscoverDevices());
            PrintDevices();
        }

        /// <summary>
        /// 获取本机蓝牙设备地址
        /// </summary>
        /// <returns>本机蓝牙设备地址</returns>
        private BluetoothAddress LocalAddress()
        {
            if (PrimaryRadio == null)
            {
                Console.WriteLine("No radio hardware or unsupported software stack");
                return null;
            }
            // Note that LocalAddress is null if the radio is powered-off.
            //Console.WriteLine("* Radio, address: {0:C}", primaryRadio.LocalAddress);
            return PrimaryRadio.LocalAddress;
        }

        /// <summary>
        /// 更新本机的蓝牙客户端
        /// </summary>
        public void UpdateClient()
        {
            if (LocalClient != null)
            {
                LocalClient.Close();
                LocalClient = new BluetoothClient { InquiryLength = this.InquiryLength };
                //LocalClient.InquiryLength = this.InquiryLength;
            }
        }

        /// <summary>
        /// 串口数据接收
        /// </summary>
        /// <returns></returns>
        public Task DataReceived()
        {
            return Task.Factory.StartNew(() =>
            {
                while (true)
                {
                    //if (!PauseRecvData.SafeWaitHandle.IsClosed)
                    //{
                    //    if (PauseRecvData.WaitOne())
                    //    {
                    //        //ClearSerialBuffer();
                    //    }
                    //}

                    //timer.Restart();
                    //Logger.Trace($"串口数据接收=>len=【{len}】");
                    try
                    {
                        if (!LocalClient.Connected)
                        {
                            continue;
                        }

                        stream = LocalClient.GetStream();
                        Received?.Invoke(btDeviceInfo, client, stream);

                        var dataLen = client.Available;
                        if (dataLen > 0)
                        {
                            byte[] buffer = new byte[dataLen];
                            stream.Read(buffer, 0, dataLen);

                            var hexStr = BitConverter.ToString(buffer, 0, dataLen);
                            Trace.WriteLine(hexStr);

                            rqRawData.Enqueue(buffer);
                        }
                    }
                    catch (Exception ex)
                    {
                        string message = $"接收串口数据发生异常：{ex.Message}如果是因为串口被拔出请重新插回！".Replace("\r\n", "");
                        //logger.Fatal(message, ex);
                        //UpdateComStatus?.Invoke(false, PortName, message);
                    }
                    //timer.Stop();
                    //var timeSpan = sw.ElapsedMilliseconds;
                    //Trace.WriteLine($"串口数据接收=>本次接收耗时:{timeSpan}毫秒");
                }
            }, TaskCreationOptions.LongRunning);
        }

        public byte[] GetNewFrame()
        {
            if (rqRawData.TryDequeue(out byte[] result))
            {
                return result;
            }
            return null;
        }

        /// <summary>
        /// 从数据队列中取出新一帧(已废弃)
        /// </summary>
        /// <returns>正确的单帧数据</returns>
        //public byte[] GetNewFrame(byte funCode, bool isCancell = false)
        //{
        //    //Monitor.Enter(SyncRoot);
        //    var iterationLength = FixedPrefix.BytesLength;
        //    List<byte> affixData = new List<byte>();// 缓存词缀(固定帧头/帧尾)专用
        //    List<byte> recvData = new List<byte>();
        //    while (!isCancell)
        //    {
        //        while (affixData.Count < iterationLength)// 这个while循环耗时十几ms到一百ms左右
        //        {// 接收数据长度不足接收数据帧长度则继续从队列中拉取
        //            if (rqRawData.IsEmpty)
        //            {
        //                //Debug.WriteLine($"串口数据处理=>0-recvDataQueue.Count=【{recvDataQueue.Count}】");
        //                continue;
        //            }

        //            if (rqRawData.TryDequeue(out byte item))
        //            {
        //                affixData.Add(item);
        //                recvData.Add(item);
        //            }
        //        }

        //        if (affixData.ToArray().IsEqual(FixedPrefix.Bytes))
        //        {// 词缀为固定帧头时
        //            affixData.Clear();
        //            iterationLength = FixedSuffix.BytesLength;// 重设迭代长度找固定帧尾
        //            var removeCount = recvData.Count - FixedPrefix.BytesLength;// 计算recvData中需在固定帧头前移除的数据量
        //            recvData.RemoveRange(0, removeCount);// 移除recvData中固定帧头前的数据
        //            continue;
        //        }
        //        else if (affixData.ToArray().IsEqual(FixedSuffix.Bytes))
        //        {// 词缀为固定帧尾时
        //            affixData.Clear();
        //            iterationLength = FixedPrefix.BytesLength;// 重设迭代长度找固定帧头
        //        }
        //        else
        //        {// 不是词缀时
        //            affixData.RemoveAt(0);
        //            continue;
        //        }

        //        (int code, byte[] ackData) = GetAckDataFromBuffer(recvData, funCode);// 取出应答数据

        //        //if (code == 0)
        //        //{
        //        //    recvFrame = ackData;
        //        //    break;
        //        //}
        //        //else
        //        //{
        //        //    continue;
        //        //}
        //        if (code == 0)
        //        {
        //            recvFrame = ackData;
        //        }
        //        break;
        //    }
        //    //Monitor.Exit(SyncRoot);
        //    return recvFrame;
        //}

        /// <summary>
        /// 返回蓝牙mac地址的“-”连接符形式
        /// </summary>
        /// <param name="bluetoothAdress">“:”连接符形式的蓝牙mac地址</param>
        /// <returns>“-”连接符形式的蓝牙mac地址</returns>
        public string StripBluetoothAdress(string bluetoothAdress)
        {
            var charsToRemove = new string[] { ":", "-" };
            return charsToRemove.Aggregate(bluetoothAdress, (current, c) => current.Replace(c, string.Empty));
        }

        /// <summary>
        /// 匹配指定的蓝牙设备
        /// </summary>
        /// <param name="device">指定的蓝牙设备</param>
        /// <returns>true表示匹配成功/false表示配对失败</returns>
        public bool PairDevice(BluetoothDeviceInfo device)
        {
            if (device.Authenticated) return true;
            // loop through common PIN numbers to see if they pair
            foreach (var devicePin in CommonPins)
            {
                var isPaired = BluetoothSecurity.PairRequest(device.DeviceAddress, devicePin);
                if (isPaired) break;
            }

            //device.Update();
            device.Refresh();
            return device.Authenticated;
        }

        /// <summary>
        /// 自动配对蓝牙设备
        /// </summary>
        public void AutoPairDevices()
        {
            // get a list of all paired devices
            var paired = LocalClient.DiscoverDevices();
            // check every discovered device if it is already paired 
            foreach (var device in DeviceInfoList)
            {
                var isPaired = paired.Any(t => device.Equals(t));

                // if the device is not paired, try to pair it
                if (!isPaired)
                {
                    // loop through common PIN numbers to see if they pair
                    foreach (var devicePin in CommonPins)
                    {
                        isPaired = BluetoothSecurity.PairRequest(device.DeviceAddress, devicePin);
                        if (isPaired) break;
                    }
                }
            }
        }

        /// <summary>
        /// 连接经典蓝牙设备
        /// </summary>
        /// <param name="device">经典蓝牙设备</param>
        /// <param name="devicePin">设备引脚</param>
        public void ConnectBTDevice(BluetoothDeviceInfo device, string devicePin = null)
        {
            // set pin of device to connect with
            //if (devicePin != null) LocalClient.SetPin(devicePin);

            // check if device is paired
            if (device.Authenticated)
            {
                // synchronous connection method
                LocalClient.Connect(device.DeviceAddress, Guid);
                if (LocalClient.Connected)
                {
                    stream = LocalClient.GetStream();
                }
                stream.ReadTimeout = 500;
            }
        }

        /// <summary>
        /// 连接经典蓝牙设备
        /// </summary>
        /// <param name="deviceId">经典蓝牙设备的Id</param>
        public void ConnectBTDevice(int deviceId)
        {
            var device = DeviceInfoList[deviceId];
            ConnectBTDevice(device, null);
        }

        /// <summary>
        /// 获取串口
        /// </summary>
        /// <returns></returns>
        public List<SerialPort> GetSerialPorts()
        {
            var portIdentifiers = new[]
                {
                    "bthenum","btmodem","btport"
                };
            var portList = new List<SerialPort>();
            const string win32SerialPort = "Win32_SerialPort";
            var query = new SelectQuery(win32SerialPort);
            var managementObjectSearcher = new ManagementObjectSearcher(query);
            var portslist = managementObjectSearcher.Get();
            foreach (var port in portslist)
            {
                var managementObject = (ManagementObject)port;
                var deviceId = managementObject.GetPropertyValue("DeviceID").ToString();
                var pnpDeviceId = managementObject.GetPropertyValue("PNPDeviceID").ToString().ToLower();

                if (portIdentifiers.Any(pnpDeviceId.Contains))
                {
                    portList.Add(new SerialPort { Port = deviceId, DeviceId = pnpDeviceId });
                }
            }
            return portList;
        }

        /// <summary>
        /// 写入值到寄存器(仅限于经典蓝牙操作)
        /// </summary>
        /// <param name="value">寄存器的值，文本内容请事先转换为byte数组以防止转码不通用的问题</param>
        /// <returns>true表示写入成功，false表示写入失败</returns>
        public bool WriteRegister(byte[] sendBuffer)
        {
            bool ret = false;
            try
            {
                if (sendBuffer == null) throw new ArgumentNullException(nameof(sendBuffer));
#if DEBUG
                //var rawHexStr = StringLib.GetHexStringFromByteArray(sendbuffer);
                //var rawHexStr = sendBuffer.ToHexString();
#endif
                if (stream != null)
                {
                    stream.Flush();// 清空缓冲区
                    stream.Write(sendBuffer, 0, sendBuffer.Length);
#if DEBUG
                    //Trace.WriteLine($"发送指令：{rawHexStr}");
#endif
                    ret = true;
                }
            }
            catch
            {
                throw;
            }
            return ret;
        }

        /// <summary>
        /// 写入值到寄存器然后接收应答(仅限于经典蓝牙操作)
        /// </summary>
        /// <param name="value">寄存器的值，文本内容请事先转换为byte数组以防止转码不通用的问题</param>
        /// <returns>返回下位机响应的数据流</returns>
        public List<byte> WriteRegisterThenRecvAck(byte[] values)
        {
            List<byte> recBuffer = null;
            try
            {
                if (values == null) throw new ArgumentNullException(nameof(values));
                if (stream != null)
                {
                    recBuffer = SendDataRec(values);
                }
            }
            catch
            {
                throw;
            }
            return recBuffer;
        }

        /// <summary>
        /// 写入值到寄存器
        /// </summary>
        /// <param name="funCode">控制模式</param>
        /// <param name="value">寄存器的值，文本内容请事先转换为byte数组以防止转码不通用的问题</param>
        /// <returns>true表示写入成功，false表示写入失败</returns>
        public async Task<bool> WriteRegisterAsync(BluetoothType btType, byte[] values)
        {
            bool ret = false;
            try
            {
                if (values == null) throw new ArgumentNullException(nameof(values));
#if DEBUG
                //var rawHexStr = StringLib.GetHexStringFromByteArray(values);
                //var rawHexStr = sendBuffer.ToHexString();
#endif

                if (stream != null)
                {
                    switch (btType)
                    {
                        case BluetoothType.BluetoothClassic:
                            await stream.WriteAsync(values, 0, values.Length);
                            break;
                        case BluetoothType.BluetoothLowEnergy:
                            //await nusWriteChtt.WriteValueWithoutResponseAsync(sendBuffer);
                            break;
                    }

#if DEBUG
                    //Trace.WriteLine($"发送指令：{rawHexStr}");
#endif
                    ret = true;
                }
            }
            catch
            {
                throw;
            }
            return ret;
        }

        /// <summary>
        /// 写入值到寄存器然后接收应答
        /// </summary>
        /// <param name="funCode">控制模式</param>
        /// <param name="value">寄存器的值，文本内容请事先转换为byte数组以防止转码不通用的问题</param>
        /// <returns>返回下位机响应的数据流</returns>
        public async Task<byte[]> WriteRegisterThenRecvAckAsync<T>(byte funCode, params T[] values)
        {
            byte[] recBuffer = null;
            try
            {
                //var recvData = await SendDataRecAsync(sendBuffer);
                //if (recvData != null)
                //{
                //    (int code, byte[] ackData) = GetAckDataFromBuffer(recvData, funCode);// 取出应答数据
                //    if (code == 0)
                //    {
                //        recBuffer = ackData;
                //    }
                //}
            }
            catch
            {
                throw;
            }
            return recBuffer;
        }

        /// <summary>
        /// 打印几个枚举和常量的子项
        /// </summary>
        public void PrintEnumsAndConstCollection()
        {
            var items = Enum.GetValues(typeof(BluetoothLEAppearance));
            Console.WriteLine($"BluetoothLEAppearance总计包含{items.Length}个枚举项：");
            foreach (var item in items)
            {
                Console.WriteLine($"{item}:{(ushort)item}");
            }

            items = Enum.GetValues(typeof(ServiceClass));
            Console.WriteLine($"\r\nServiceClass总计包含{items.Length}个枚举项：");
            foreach (var item in items)
            {
                Console.WriteLine($"{item}:{(int)item}");
            }

            var gsuLst = GetFieldInfo(typeof(GattServiceUuids));
            Console.WriteLine($"\r\nGattServiceUuids总计包含{gsuLst.Count}个Uuid：");
            gsuLst.ForEach(x => Console.WriteLine($"{x.name}:{x.value}"));

            var gcuLst = GetFieldInfo(typeof(GattCharacteristicUuids));
            Console.WriteLine($"\r\nGattCharacteristicUuids总计包含{gcuLst.Count}个Uuid：");
            gcuLst.ForEach(x => Console.WriteLine($"{x.name}:{x.value}"));
        }

        /// <summary>
        /// 打印串口
        /// </summary>
        public void PrintSerialPorts()
        {
            var portList = GetSerialPorts();
            foreach (var port in portList)
            {
                Console.WriteLine("Port: {0}, name: {1}", port.Port, port.DeviceId);
            }
        }

        /// <summary>
        /// 打印本机蓝牙地址
        /// </summary>
        public void PrintLocalAddress()
        {
            var localBluetoothAddress = LocalAddress();

            if (localBluetoothAddress == null) return;
            Console.WriteLine("{0:C}", localBluetoothAddress);
        }

        /// <summary>
        /// 打印蓝牙设备信息
        /// </summary>
        /// <param name="device"></param>
        public void PrintDevice(BluetoothDeviceInfo device)
        {
            // log and save all found devices
            Console.Write(device.DeviceName + " (" + device.DeviceAddress + "): Device is ");
            //Console.Write(device.Remembered ? "remembered" : "not remembered");
            Console.Write(device.Authenticated ? ", paired" : ", not paired");
            Console.WriteLine(device.Connected ? ", connected" : ", not connected");
        }
        #endregion 公开方法 end

        #region    私有方法 start
        /// <summary>
        /// 打印所有蓝牙设备信息
        /// </summary>
        private void PrintDevices()
        {
            // log and save all found devices
            foreach (var t in DeviceInfoList)
            {
                PrintDevice(t);
            }
        }

        /// <summary>
        /// 返回静态类中的所有静态子段的名称和值
        /// </summary>
        /// <typeparam name="T">静态类的类型</typeparam>
        /// <returns>静态子段的名称和值</returns>
        private List<(string name, string value)> GetFieldInfo(Type staticClassType)
        {
            var result = new List<(string name, string value)>();
            //Type staticClassType = typeof(T);
            FieldInfo[] fields = staticClassType.GetFields(BindingFlags.Public | BindingFlags.Static);

            foreach (FieldInfo field in fields)
            {
                if (field.FieldType == typeof(BluetoothUuid))
                {
                    string fieldName = field.Name;
                    var fieldValue = field.GetValue(null)?.ToString();
                    //var fieldValue = val == null ? "" : $"0x{val}";
                    result.Add((fieldName, fieldValue));
                }
            }
            return result;
        }

        /// <summary>
        /// 发送并且接收字节数组
        /// </summary>
        /// <param name="sendBuffer"></param>
        /// <param name="recbuffer"></param>
        /// <returns></returns>
        private List<byte> SendDataRec(byte[] sendBuffer)
        {
            List<byte> total = new List<byte>();
            try
            {
                // 发送数据
                stream.Write(sendBuffer, 0, sendBuffer.Length);
#if DEBUG
                //var rawHexStr = StringLib.GetHexStringFromByteArray(sendBuffer);
                //var rawHexStr = sendBuffer.ToHexString();
                //logger.Info($"发送指令：{rawHexStr}");
#endif

                byte[] buffer = null;
                int counts = 0;
                DateTime startTime = DateTime.Now;
                while (true)
                {
                    int len = client.Available;
                    if (len > 0)
                    {
                        buffer = new byte[len];
                        counts = stream.Read(buffer, 0, len);
                        if (counts > 0)
                        {
                            total.AddRange(buffer);
                        }
                    }
                    else
                    {
                        Thread.Sleep(10);
                        if ((DateTime.Now - startTime).TotalMilliseconds > stream.ReadTimeout)
                        {// 超时
                            break;
                        }
                    }
                }
            }
#if DEBUG
            catch (Exception ex)
            {
                Trace.WriteLine($"WriteCommand异常=>{ex.Message}");
#else
            catch
            {
#endif
                throw;
            }
            return total;
        }

        /// <summary>
        /// 发送并且接收字节数组
        /// </summary>
        /// <param name="sendBuffer"></param>
        /// <param name="recbuffer"></param>
        /// <returns></returns>
        private async Task<List<byte>> SendDataRecAsync(byte[] sendBuffer)
        {
            List<byte> total = new List<byte>();
            try
            {
                // 发送数据
                stream.Write(sendBuffer, 0, sendBuffer.Length);
#if DEBUG
                //var rawHexStr = StringLib.GetHexStringFromByteArray(sendBuffer);
                //var rawHexStr = sendBuffer.ToHexString();
                //logger.Info($"发送指令：{rawHexStr}");
#endif

                byte[] buffer = null;
                int counts = 0;
                DateTime startTime = DateTime.Now;
                while (true)
                {
                    int len = client.Available;
                    if (len > 0)
                    {
                        buffer = new byte[len];
                        counts = await stream.ReadAsync(buffer, 0, len);
                        if (counts > 0)
                        {
                            total.AddRange(buffer);
                        }
                    }
                    else
                    {
                        Thread.Sleep(10);
                        if ((DateTime.Now - startTime).TotalMilliseconds > stream.ReadTimeout)
                        {// 超时
                            break;
                        }
                    }
                }
            }
#if DEBUG
            catch (Exception ex)
            {
                Trace.WriteLine($"WriteCommand异常=>{ex.Message}");
#else
            catch
            {
#endif
                throw;
            }
            return total;
        }
        #endregion 私有方法 end
    }
}